IEEE compliance to Floating-Point hardware in microprocessors has traditionally been a challenging task to achieve. Many escape bugs, including the infamous Pentium bug, belong to the floating-point unit and reveal that the verification process in this area is still far from being optimal. The ever-growing demand for performance and time-to-market causes the verification work to become increasingly harder. So does the low tolerance for bugs on the finished product. There are many sources of problems in the implementation of the Floating-Point unit, ranging from data problems on single instructions to the correct handling of sequences of instructions in which back-to-back events challenge superscalar implementations. The roots of the complexity stem, inter alia, both from the interpretation of the specification (architecture) and from the peculiarities of the implementation (microarchitecture). Verification has traditionally been targeted through the simulation of test-programs [5, 6]. Lately, the area of formal methods has significantly evolved, especially for the floating-point unit verification [1–4], but is still far from providing a complete answer to the problem.
Hence, in most environments, the simulation of test cases is still a major component of the verification process. Normally, for each event (test case) a customized procedure should be prepared. It is, therefore, readily appreciated that preparing numerous procedures for the many different calculation cases to test is a very labor-intensive task. In practice, then, simulation can be carried out on only a very small portion of the existing space. The rationale beyond verification by simulation is that one acquires confidence on design correctness by running a set of test cases exercising a sufficiently large number of different cases, which, in some sense, are assumed to be a representative sample of the full space. It is inferred that the correct handling of the tested cases is a testimony for the design correctness of all cases. The difficult question is how to define such a representative set of test cases. Since both the architecture specification and the microarchitecture implementation yield a myriad of special cases, relying on pure (uniform) random test cases would be largely inefficient.
How does one know that a certain set of tests is sufficient? This question is related to the notion of coverage, i.e., to the comprehensiveness of the set related to the verification target [9–12]. Usually, coverage models are defined and the set of tests should fulfill all the existing tasks. A coverage model is a set of related cases.
For example, a common coverage model is one which requires to enumerate on all major IEEE Floating-Point types simultaneously for all operands of all FP instructions. For a given instruction with three operands, say ADD, this potentially yields a thousand (103) of cases to cover, assuming 10 major FP types (+/−NaNs, +/−Infinity, +/−Zero, +/−Denormal, +/−Normal). This model can be further refined by adding more FP types, such as Minimum and Maximum denormals, etc. Obviously, not all cases are possible (e.g. the addition of 2 positive denormal numbers cannot reach infinity), so that the actual number of cases is, in fact, lower than the size of the Cartesian product.
A coverage model or a set of all coverage models is typically (but not necessarily) an attempt to partition the set of all the calculation cases in such a way that the probability distribution should be similar for all subsets. There is, thus, a need in the art to substantially reduce the drawbacks of hitherto known solutions for verifying Floating-Point standard compliance.
Still further, there is a need in the art to provide for an improved technique for verifying a compliance with Floating-Point standards by defining Floating-Point events of interest and, if desired, regrouping them into coverage models.
Still further, there is a need in the art to provide for a computer language or computer language specification which enables to define Floating-Point events of interest and, if desired, regrouping them into coverage models. Such a language can be used for various applications, e.g. evaluation of coverage of tests being run on a design.